%{
    #include <cwchar>
    #include <cstdio>
    #include <ios>
    #include <iosfwd>
    #include <locale>
%}

%include Common.i
%include <std_string.i>

%define WARP_STREAM_TYPE(CONST ,TYPE)
%typemap(cstype) TYPE*, TYPE&, CONST TYPE*, CONST TYPE& "global::System.IntPtr"
%typemap(imtype, out="global::System.IntPtr") TYPE*, TYPE&, CONST TYPE*, CONST TYPE& "global::System.IntPtr"
%typemap(csin) TYPE*, TYPE&, CONST TYPE*, CONST TYPE& "$csinput"
%typemap(csout, excode=SWIGEXCODE) TYPE*, TYPE&, CONST TYPE*, CONST TYPE& {
    global::System.IntPtr cPtr = $imcall;
    return cPtr;
}
%enddef

#ifdef __GNUC__
%typemap(in) fpos_t %{
    $1.__pos = $input;
%}
#endif

%typemap(ctype) mbstate_t "long long"
%typemap(cstype) mbstate_t "long"
%typemap(imtype) mbstate_t "long"
%typemap(out) mbstate_t %{
    mbstate_t state = $1;
    long long res;
    memcpy(&res, &state, sizeof(res));
    $result = res;
%}
%typemap(in) mbstate_t %{
    mbstate_t state = { 0 };
    memcpy(&state, &$input, sizeof($input));
    $1 = state;
%}
%typemap(csin) mbstate_t "$csinput"
%typemap(csout, excode=SWIGEXCODE) mbstate_t {
    long result = $imcall;
    return result;
}

typedef long long fpos_t;
namespace std {
    typedef long long streamoff;
    typedef long long streamsize;
    template <class _Statetype>
    class fpos {
        public:
            fpos(streamoff _Off = 0);
            _Statetype state() const;
            void state(_Statetype _State);
    };
    %template(streampos) fpos<mbstate_t>;
    typedef fpos<mbstate_t> streampos;
    class locale {
        public:
            typedef int category;
            locale(const locale& _Loc, const string& _Str, category _Cat);
            string name() const;
            static const locale& classic();
            static locale global(const locale& new_default_locale);
    };
    template<class _CharT>
    struct char_traits { };
    template<>
    struct char_traits<char> {
        WARP_STREAM_TYPE(const, char)
        typedef char char_type;
        typedef int int_type;
        typedef streampos pos_type;
        typedef streamoff off_type;
        typedef mbstate_t state_type;
        static void assign(char_type& __c1, const char_type& __c2);
        static bool eq(const char_type& __c1, const char_type& __c2);
        static bool lt(const char_type& __c1, const char_type& __c2);
        static int compare(const char_type* __s1, const char_type* __s2, size_t __n);
        static size_t length(const char_type* __s);
        static const char_type* find(const char_type* __s, size_t __n, const char_type& __a);
        static char_type* move(char_type* __s1, const char_type* __s2, size_t __n);
        static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n);
        static char_type* assign(char_type* __s, size_t __n, char_type __a);
        static char_type to_char_type(const int_type& __c);
        static int_type to_int_type(const char_type& __c);
        static bool eq_int_type(const int_type& __c1, const int_type& __c2);
        static int_type eof();
        static int_type not_eof(const int_type& __c);
    };
    %template() char_traits<char>;
    class ios_base {
        public:
            ios_base() = delete;
            typedef int seekdir;
            static const seekdir beg;
            static const seekdir cur;
            static const seekdir end;

            typedef int openmode;
            static const openmode app;
            static const openmode ate;
            static const openmode binary;
            static const openmode in;
            static const openmode out;
            static const openmode trunc;

            typedef int iostate;
            static const iostate badbit;
            static const iostate eofbit;
            static const iostate failbit;
            static const iostate goodbit;

            typedef int fmtflags;
            static const fmtflags boolalpha;
            static const fmtflags dec;
            static const fmtflags fixed;
            static const fmtflags hex;
            static const fmtflags internal;
            static const fmtflags left;
            static const fmtflags oct;
            static const fmtflags right;
            static const fmtflags scientific;
            static const fmtflags showbase;
            static const fmtflags showpoint;
            static const fmtflags showpos;
            static const fmtflags skipws;
            static const fmtflags unitbuf;
            static const fmtflags uppercase;
            static const fmtflags adjustfield;
            static const fmtflags basefield;
            static const fmtflags floatfield;

            inline fmtflags flags() const;
            inline fmtflags flags(fmtflags __fmtfl);
            inline fmtflags setf(fmtflags __fmtfl);
            inline fmtflags setf(fmtflags __fmtfl, fmtflags __mask);
            inline void unsetf(fmtflags __mask);
            inline streamsize precision() const;
            inline streamsize width() const;
            inline streamsize width(streamsize __wide);
            static bool sync_with_stdio(bool __sync = true);
            locale imbue(const locale& __loc);
            inline locale getloc() const;
            inline void*& pword(int __ix);
        protected:
            ios_base();
    };

    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_istream;
    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_ostream;
    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_streambuf;
    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_ios : public ios_base {
        public:
            typedef _CharT char_type;
            typedef typename _Traits::int_type int_type;
            typedef typename _Traits::pos_type pos_type;
            typedef typename _Traits::off_type off_type;
            typedef _Traits traits_type;
        public:
            iostate rdstate() const;
            void clear(iostate __state = goodbit);
            void setstate(iostate __state);
            bool good() const;
            bool eof() const;
            bool fail() const;
            bool bad() const;
            iostate exceptions() const;
            void exceptions(iostate __except);
            explicit basic_ios(basic_streambuf<_CharT, _Traits>* __sb) : ios_base();
            basic_ostream<_CharT, _Traits>* tie() const;
            basic_ostream<_CharT, _Traits>* tie(basic_ostream<_CharT, _Traits>* __tiestr);
            basic_streambuf<_CharT, _Traits>* rdbuf() const;
            basic_streambuf<_CharT, _Traits>* rdbuf(basic_streambuf<_CharT, _Traits>* __sb);
            basic_ios& copyfmt(const basic_ios& __rhs);
            char_type fill() const;
            char_type fill(char_type __ch);
            locale imbue(const locale& __loc);
            char narrow(char_type __c, char __dfault) const;
            char_type widen(char __c) const;
        protected:
            basic_ios();
    };
}

namespace std {
    %template(ios) basic_ios<char>;
    typedef basic_ios<char> ios;
}

